<?php
namespace App\Models\AuthManage;

use Illuminate\Support\Facades\DB;

/**
 * 菜单管理
 * Class MenuModel
 * @package app\back\model
 */
class MenuModel{
	/**
	 * 创建菜单
	 * @param $data
	 * @return array
	 * @throws \Exception
	 */
	public function addMenu($data) {
		$nowTime = time();
		$insertData = [
			'menu_type'	=>	1,
			'parent_id'	=>	$data['parentId'],
			'name'		=>	$data['name'],
			'description'	=>	isset($data['description']) ? $data['description'] : "",
			'key_val'	=>	isset($data['keyVal']) ? $data['keyVal'] : "",
			'url'		=>	isset($data['url']) ? $data['url'] : "",
			'icon'		=>	isset($data['icon']) ? $data['icon'] : "",
			'include_str'	=>	isset($data['includeStr']) ? $data['includeStr'] : "",
			'sort'		=>	isset($data['sort']) ? (int)$data['sort'] : 0,
			'create_time'	=>	$nowTime,
			'update_time'	=>	$nowTime,
			'status'	=>	1,
			'depth'		=>	'|'
		];

		if ($data['parentId'] > 0) {
			$isExits = DB::table('sc_system_menu')->where('id', $data['parentId'])->select(['id','depth'])->first();
			if (!$isExits) {
				return ModelReturn(1, '父级菜单不存在');
			}

			$insertData['depth'] = $isExits->depth;
		}

		$iCnt = DB::table('sc_system_menu')->insertGetId($insertData);
		if ($iCnt) {
			DB::table('sc_system_menu')->where('id', $iCnt)->update([
				'depth'	=>	'|' . $iCnt . $insertData['depth']
			]);
			HandleLog()->addLog('i', $data, '创建了菜单:'.$data['name']);
			return ModelReturn(0, '创建成功');
		} else {
			return ModelReturn(2, '创建失败');
		}
	}

	/**
	 * 编辑菜单
	 * @param $data
	 * @return array
	 * @throws \Exception
	 */
	public function editMenu($data) {
		if ($data['parentId'] == $data['id']) {
			return ModelReturn(4, '修改的父级ID不能与自身ID一致');
		}

		$nowTime = time();
		$updateData = [
			'parent_id'	=>	$data['parentId'],
			'name'		=>	$data['name'],
			'description'	=>	isset($data['description']) ? $data['description'] : "",
			'key_val'	=>	isset($data['keyVal']) ? $data['keyVal'] : "",
			'url'		=>	isset($data['url']) ? $data['url'] : "",
			'icon'		=>	isset($data['icon']) ? $data['icon'] : "",
			'include_str'	=>	isset($data['includeStr']) ? $data['includeStr'] : "",
			'sort'		=>	isset($data['sort']) ? (int)$data['sort'] : 0,
			'update_time'	=>	$nowTime
		];

		$id = $data['id'];
		if ($data['parentId'] > 0) {
			$parentObj = DB::table('sc_system_menu')->where('id', $data['parentId'])->select(['id','depth'])->first();
			if (!$parentObj) {
				return ModelReturn(1, '父级菜单不存在');
			}
		}

		$menuObj = DB::table('sc_system_menu')->where('id', $id)->select(['id','name','depth','parent_id'])->first();
		if (!$menuObj) {
			return ModelReturn(2, '菜单不存在');
		}

		if ($menuObj->parent_id != $data['parentId']) {
			$newParentDepth = "|{$menuObj->id}";
			if ($data['parentId'] > 0) {
				$newParentDepth .= $parentObj->depth;
			} else {
				$newParentDepth .= '|';
			}
			$updateData['depth'] = $newParentDepth;
		}

		$iCnt = DB::table('sc_system_menu')->where('id', $id)->update($updateData);
		if ($iCnt) {
			$needUpdateChildId = [$id];
			$depthList = [$id=>$updateData['depth'] ?? $menuObj->depth];
			while ($parentChangeId = array_pop($needUpdateChildId)) {
				$allChildList = DB::table('sc_system_menu')->where('parent_id', $parentChangeId)->get();
				foreach ($allChildList as $item) {
					if (!array_key_exists($parentChangeId, $depthList)) {
						continue;
					}
					$newDepth = '|' . $item->id . $depthList[$parentChangeId];
					DB::table('sc_system_menu')->where('id', $item->id)->update(['depth'=>$newDepth]);
					$depthList[$item->id] = $newDepth;
					$needUpdateChildId[] = $item->id;
				}
			}

			HandleLog()->addLog('u', $data, '编辑了菜单'.$menuObj->name);
			return ModelReturn(0, '修改成功');
		} else {
			return ModelReturn(3, '修改失败');
		}
	}

	/**
	 * 获取菜单树状数据结构
	 * @return array
	 */
	public function getMenuListTree() {
		$allMenuList = DB::table('sc_system_menu')->whereRaw('status!=9')->orderByRaw('sort desc,create_time desc')->get();
		$menuTree = [];
		$allMenuListData = [];
		foreach ($allMenuList as $item) {
			$item = (array)$item;
			$item['childList'] = [];
			$allMenuListData[$item['id']] = $item;
		}

		foreach ($allMenuListData as &$item) {
			if ($item['parent_id'] == 0) {
				$menuTree[$item['id']] = &$item;
			} else {
				if (array_key_exists($item['parent_id'], $allMenuListData)) {
					$allMenuListData[$item['parent_id']]['childList'][$item['id']] = &$item;
				}
			}
		}
		return $menuTree;
	}

	/**
	 * 删除菜单
	 * @param $data
	 * @return array
	 */
	public function deleteMenu($data) {
		$id = (int)$data['id'];
		$menuObj = DB::table('sc_system_menu')->where('id', $id)->select(['id','name'])->first();
		if (!$menuObj) {
			return ModelReturn(1, '菜单不存在');
		}

		$menuTree = $this->getMenuListTree();
		$needDeleteId = [$id];
		while ($item = array_pop($menuTree)) {
			if (in_array($item['id'], $needDeleteId)) {
				$needDeleteId = array_merge($needDeleteId, array_keys($item['childList']));
			}
			$menuTree =array_merge($menuTree,  $item['childList']);
		}
		$iCnt = DB::table('sc_system_menu')->whereIn('id', $needDeleteId)->update(['status'=>9, 'update_time'=>time()]);
		if ($iCnt) {
			return ModelReturn(0, '删除成功');
		} else {
			return ModelReturn(2, '删除失败');
		}
	}

	/**
	 * 获取菜单详情
	 * @param $id
	 * @return array
	 */
	public function getMenu($id) {
		$menuObj = DB::table('sc_system_menu')->where('id', $id)->first();
		if (!$menuObj) {
			return ModelReturn(1, '菜单不存在');
		}

		$menuObj = (array)$menuObj;
		$menuObj['depthArr'] = array_reverse(explode('|', trim($menuObj['depth'], '|')));
		return ModelReturn(0, '获取成功', $menuObj);
	}

	/**
	 * 获取菜单列表
	 * @param $name
	 * @param int $page
	 * @param int $limit
	 * @return array
	 */
	public function getMenuList($name, $page=1, $limit=10) {
		$menuListObj = DB::table('sc_system_menu as t1')->leftJoin('sc_system_menu as t2', 't1.parent_id','=','t2.id')->whereRaw('t1.status!=9')->orderByRaw('t1.sort desc,t1.create_time desc')->select(['t1.*','t2.name as parentName']);
		if ($name) {
			$menuListObj->whereRaw("t1.name like '%$name%'");
		}
		$index = ($page - 1) * $limit;
		$totalObj = clone $menuListObj;
		$total = $totalObj->count('t1.id');
		$menuListData = $menuListObj->offset($index)->limit($limit)->get();
		$menuListData = DbObjectToArr($menuListData);

		$allFunctionList = [];
		if ($menuListData) {
			$allMenuList = array_column($menuListData, 'id');
			$allFunctionList = DB::table('sc_system_function')->whereIn('menu_id', $allMenuList)->groupBy('menu_id')->pluck(Db::raw("COUNT(menu_id) as functionNum"),"menu_id");
		}

		array_walk($menuListData, function (&$item) use($allFunctionList){
			$item['menu_type_str'] = $item['menu_type'] == 1 ? 'PC' : '';
			$item['parentName'] = $item['parentName'] ? : "根";
			$item['createTimeStr'] = date("Y-m-d H:i:s", $item['create_time']);
			$item['updateTimeStr'] = date("Y-m-d H:i:s", $item['update_time']);
			$item['functionNum'] = array_key_exists($item['id'], $allFunctionList) ? $allFunctionList[$item['id']] : 0;
		});

		$data = [
			'total'	=>	$total,
			'list'	=>	$menuListData,
			'limit'	=>	$limit,
			'page'	=>	$page
		];

		return ModelReturn(0, '获取成功', $data);
	}

	/**
	 * 创建功能
	 * @param $data
	 * @return array
	 * @throws \Exception
	 */
	public function addFunction($data) {
		$nowTime = time();
		$insertData = [
			'menu_id'	=>	$data['id'],
			'name'		=>	$data['functionName'],
			'key_val'	=>	isset($data['keyVal']) ? $data['keyVal'] : "",
			'create_time'	=>	$nowTime,
			'update_time'	=>	$nowTime,
			'status'	=>	1
		];

		$menuObj = DB::table('sc_system_menu')->where('id', $data['id'])->whereRaw("status!=9")->first();
		if (!$menuObj) {
			return ModelReturn(1, '菜单不存在');
		}

		$iCnt = DB::table('sc_system_function')->insert($insertData);
		if ($iCnt) {
			HandleLog()->addLog('i', $data, '创建了菜单'. $menuObj->name .'的功能:' . $data['functionName']);
			return ModelReturn(0, '创建成功');
		} else {
			return ModelReturn(2, '创建失败');
		}
	}

	/**
	 * 编辑功能
	 * @param $data
	 * @return array
	 * @throws \Exception
	 */
	public function editFunction($data) {
		$id = $data['functionId'];
		$nowTime = time();
		$updateData = [
			'name'		=>	$data['functionName'],
			'key_val'	=>	isset($data['keyVal']) ? $data['keyVal'] : "",
			'update_time'	=>	$nowTime
		];

		$functionObj = DB::table('sc_system_function')->where('id', $id)->whereRaw("status!=9")->first();
		if (!$functionObj) {
			return ModelReturn(1, '功能不存在');
		}

		$iCnt = DB::table('sc_system_function')->where('id', $id)->update($updateData);
		if ($iCnt) {
			HandleLog()->addLog('u', $data, '修改了功能' . $functionObj->name . '的信息');
			return ModelReturn(0, '编辑成功');
		} else {
			return ModelReturn(2, '编辑失败');
		}
	}

	/**
	 * 删除功能
	 * @param $id
	 * @return array
	 * @throws \Exception
	 */
	public function deleteFunction($id) {
		$functionObj = DB::table('sc_system_function')->where('id', $id)->whereRaw("status!=9")->first();
		if (!$functionObj) {
			return ModelReturn(1, '功能不存在');
		}

		$iCnt = DB::table('sc_system_function')->where('id', $id)->update([
			'update_time'	=>	time(),
			'status'		=>	9
		]);
		if ($iCnt) {
			HandleLog()->addLog('d', ['id'=>$id], '删除了功能'. $functionObj->name);
			return ModelReturn(0, '删除成功');
		} else {
			return ModelReturn(2, '删除失败');
		}
	}

	/**
	 * 获取功能详情
	 * @param $id
	 * @return array
	 */
	public function getFunction($id) {
		$functionObj = DB::table('sc_system_function')->where('id', $id)->whereRaw("status!=9")->first();
		if (!$functionObj) {
			return ModelReturn(1, '功能不存在');
		}

		return ModelReturn(0, '获取成功', $functionObj);
	}

	/**
	 * 获取功能列表
	 * @param $menuId
	 * @param int $page
	 * @param int $limit
	 * @return array
	 */
	public function getFunctionList($menuId, $page=1, $limit=10) {
		$index = ($page - 1) * $limit;
		$total =  DB::table('sc_system_function')->where('menu_id', $menuId)->count('id');
		$functionList = DB::table('sc_system_function')->where('menu_id', $menuId)->whereRaw('status!=9')->orderBy('id')->offset($index)->limit($limit)->get();
		$functionList = DbObjectToArr($functionList);
		$data = [
			'total'	=>	$total,
			'list'	=>	$functionList,
			'limit'	=>	$limit,
			'page'	=>	$page
		];

		return ModelReturn(0, '获取成功', $data);
	}

	/**
	 * 添加权限路由
	 * @param $data
	 * @return array
	 * @throws \Exception
	 */
	public function addApiRoute($data) {
		$nowTime = time();
		$insertData = [
			'menu_id'	=>	$data['id'],
			'name'		=>	$data['apiRouteName'],
			'url'		=>	$data['apiRouteUrl'],
			'description'	=>	isset($data['description']) ? $data['description'] : "",
			'create_time'	=>	$nowTime,
			'update_time'	=>	$nowTime,
			'status'	=>	1
		];

		$menuObj = DB::table('sc_system_menu')->where('id', $data['id'])->whereRaw("status!=9")->first();
		if (!$menuObj) {
			return ModelReturn(1, '菜单不存在');
		}

		$iCnt = DB::table('sc_system_api')->insert($insertData);
		if ($iCnt) {
			HandleLog()->addLog('i', $data, '创建了菜单'. $menuObj->name .'的权限:' . $data['apiRouteName']);
			return ModelReturn(0, '创建成功');
		} else {
			return ModelReturn(2, '创建失败');
		}
	}

	/**
	 * 编辑权限路由
	 * @param $data
	 * @return array
	 * @throws \Exception
	 */
	public function editApiRoute($data) {
		$id = $data['apiRouteId'];
		$nowTime = time();
		$updateData = [
			'name'		=>	$data['apiRouteName'],
			'description'	=>	isset($data['description']) ? $data['description'] : "",
			'url'			=>	$data['apiRouteUrl'],
			'update_time'	=>	$nowTime
		];

		$apiObj = DB::table('sc_system_api')->where('id', $id)->whereRaw("status!=9")->first();
		if (!$apiObj) {
			return ModelReturn(1, '功能不存在');
		}

		$iCnt = DB::table('sc_system_api')->where('id', $id)->update($updateData);
		if ($iCnt) {
			HandleLog()->addLog('u', $data, '修改了功能' . $apiObj->name . '的信息');
			return ModelReturn(0, '编辑成功');
		} else {
			return ModelReturn(2, '编辑失败');
		}
	}

	/**
	 * 删除权限路由
	 * @param $id
	 * @return array
	 * @throws \Exception
	 */
	public function deleteApiRoute($id) {
		$apiObj = DB::table('sc_system_api')->where('id', $id)->whereRaw("status!=9")->first();
		if (!$apiObj) {
			return ModelReturn(1, 'API对象不存在');
		}

		$iCnt = DB::table('sc_system_api')->where('id', $id)->update([
			'update_time'	=>	time(),
			'status'		=>	9
		]);
		if ($iCnt) {
			HandleLog()->addLog('d', ['id'=>$id], '删除了API'. $apiObj->name);
			return ModelReturn(0, '删除成功');
		} else {
			return ModelReturn(2, '删除失败');
		}
	}

	/**
	 * 获取权限路由
	 * @param $id
	 * @return array
	 */
	public function getApiRoute($id) {
		$apiObj = DB::table('sc_system_api')->where('id', $id)->whereRaw("status!=9")->first();
		if (!$apiObj) {
			return ModelReturn(1, 'API对象不存在');
		}

		return ModelReturn(0, '获取成功', $apiObj);
	}

	/**
	 * 获取权限路由列表
	 * @param $menuId
	 * @param int $page
	 * @param int $limit
	 * @return array
	 * @throws \think\DB\exception\DataNotFoundException
	 * @throws \think\DB\exception\ModelNotFoundException
	 * @throws \think\exception\DBException
	 */
	public function getApiRouteList($menuId, $page=1, $limit=10) {
		$index = ($page - 1) * $limit;
		$total =  DB::table('sc_system_api')->where('menu_id', $menuId)->count('id');
		$functionList = DB::table('sc_system_api')->where('menu_id', $menuId)->whereRaw('status!=9')->orderBy('id')->offset($index)->limit($limit)->get();
		$functionList = DbObjectToArr($functionList);
		$data = [
			'total'	=>	$total,
			'list'	=>	$functionList,
			'limit'	=>	$limit,
			'page'	=>	$page
		];
		return ModelReturn(0, '获取成功', $data);
	}
}